﻿using System;
using System.Collections.Generic;
using DotNetNuke.Entities.Modules;
using ITM.Modules.SharePointFileExplorer.SharePoint;
using DotNetNuke.Entities.Host;
using DotNetNuke.Security;
using DotNetNuke.Entities.Users;
using Telerik.Web.UI;


namespace ITM.Modules.SharePointFileExplorer
{
    public partial class ViewFileExplorer : PortalModuleBase
    {
        // Constant values 
        private const int MBYTE = 1024 * 1024;
        private const string SKIN = "Telerik";
        // Encryption/Decryption
        private static readonly string encryptionKey = Host.GUID;
        private static readonly PortalSecurity portalSecurity = new PortalSecurity();

        // Sessioned information
        // !! this sessioned SharePoint domain is 
        // saved for later use
        public string TempSPDomian
        {
            get
            {
                if (Session["TempSPDomain"] != null)
                    return (string)Session["TempSPDomain"];
                else
                    return string.Empty;
            }
            set
            {
                Session["TempSPDomain"] = value;
            }
        }

        public Dictionary<string, string> TempSPUserName
        {
            get
            {
                if (Session["TempSPUserName"] == null)
                {
                    Dictionary<string, string> tempSPUserName = new Dictionary<string, string>();
                    tempSPUserName.Add(this.UserInfo.Username, "");
                    return tempSPUserName;
                }
                return (Dictionary<string, string>)Session["TempSPUserName"];
            }
            set
            {
                Session["TempSPUserName"] = value;
            }
        }

        public Dictionary<string, string> TempSPPassword
        {
            get
            {
                if (Session["TempSPPassword"] == null)
                {
                    Dictionary<string, string> tempSPPassword = new Dictionary<string, string>();
                    tempSPPassword.Add(this.UserInfo.Username, "");
                    return tempSPPassword;
                }
                return (Dictionary<string, string>)Session["TempSPPassword"];
            }
            set
            {
                Session["TempSPPassword"] = value;
            }
        }

        public Dictionary<string, bool> TempCredential
        {
            get
            {
                if (Session["TempCredential"] == null)
                {
                    Dictionary<string, bool> tempCredential = new Dictionary<string, bool>();
                    tempCredential.Add(this.UserInfo.Username, false);
                    return tempCredential;
                }
                return (Dictionary<string, bool>)Session["TempCredential"];
            }
            set
            {
                Session["TempCredential"] = value;
            }
        }

        protected void Page_Load(object sender, EventArgs e)
        {
            string objSelectedSPUrl = (string)Settings["SP_SELECTEDURL"];
            string objSPDomain = (string)Settings["SP_DOMAIN"];
            try
            {
                if ((objSelectedSPUrl != null) && (objSPDomain != null))
                {
                    if (!string.IsNullOrEmpty(this.UserInfo.Username))
                    {
                        panelHintMessage.Visible = false;
                        // check whether this module has been setted or not
                        string profileSPUserName = this.UserInfo.Profile.GetPropertyValue("SPUserName");
                        string profileSPPassword = this.UserInfo.Profile.GetPropertyValue("SPPassword");
                        if (string.IsNullOrEmpty(profileSPUserName) || string.IsNullOrEmpty(profileSPPassword))
                        {
                            panelUserInformation.Visible = true;
                            tbSharePointSite.Text = objSelectedSPUrl;
                            // Use sessioned information 
                            if (TempCredential.ContainsKey(this.UserInfo.Username))
                            {
                                if (TempCredential[this.UserInfo.Username] && !(chkBoxRememberInfo.Checked))
                                    BindSPInformation(DecryptInformation(TempSPUserName[this.UserInfo.Username]), DecryptInformation(TempSPPassword[this.UserInfo.Username]), objSPDomain, objSelectedSPUrl);
                            }
                        }
                        else
                        {
                            BindSPInformation(DecryptInformation(profileSPUserName), DecryptInformation(profileSPPassword.ToString()), objSPDomain, objSelectedSPUrl);
                        }
                    }
                    else
                    {
                        panelHintMessage.Visible = true;
                        panelUserInformation.Visible = false;
                        tbHintMessage.Text = "Please login using your DNN account first...";
                    }
                }
                else
                {
                    panelHintMessage.Visible = true;
                    tbHintMessage.Text = "Module needs to be set first...\nPlease contact Administrator to set it";
                }
            }
            catch (Exception ex)
            {
                panelHintMessage.Visible = true;
                panelUserInformation.Visible = true;
                panelFileExplorer.Visible = false;
                tbHintMessage.Text = "Error happened...\n" + ex.Message;
                if (TempCredential.ContainsKey(this.UserInfo.Username))
                {
                    if (TempCredential[this.UserInfo.Username])
                    {
                        tbModuleUserName.Text = DecryptInformation(TempSPUserName[this.UserInfo.Username]);
                        tbModulePassword.Attributes["Value"] = DecryptInformation(TempSPPassword[this.UserInfo.Username]);
                        // clear temporary credential
                        TempCredential = null;
                    }
                }
                else
                {
                    tbModuleUserName.Text = DecryptInformation(this.UserInfo.Profile.GetPropertyValue("SPUserName"));
                    tbModulePassword.Attributes["Value"] = DecryptInformation(this.UserInfo.Profile.GetPropertyValue("SPPassword"));
                }
            }
        }

        /// <summary>
        /// Prepare ViewPaths/UploadPaths/DeletePaths for FileExplorer
        /// </summary>
        /// <param name="username">SharePoint username</param>
        /// <param name="password">SharePoint password</param>
        /// <param name="objSPDomain">SharePoint domian</param>
        /// <param name="objSelectedSPUrl">SharePoint Url</param>
        private void BindSPInformation(string username, string password, string objSPDomain, string objSelectedSPUrl)
        {
            try
            {
                SharePointController sharepointController = new SharePointController(username, password, objSPDomain, objSelectedSPUrl);
                List<string> preparedPaths = PreparePaths(objSelectedSPUrl, sharepointController.SPGetDocumentLibraries());
                // At least has one document library, then FileExplorer can be displayed
                // otherwise it will not be shown
                if (preparedPaths.Count > 0)
                {
                    panelFileExplorer.Visible = true;
                    panelUserInformation.Visible = false;
                    panelHintMessage.Visible = false;
                    fileExplorerSP.Configuration.ContentProviderTypeName = typeof(ITM.Modules.SharePointFileExplorer.SPContentProvider).AssemblyQualifiedName;
                    fileExplorerSP.Configuration.ViewPaths = preparedPaths.ToArray();
                    fileExplorerSP.Configuration.UploadPaths = preparedPaths.ToArray();
                    fileExplorerSP.Configuration.DeletePaths = preparedPaths.ToArray();
                    fileExplorerSP.Configuration.MaxUploadFileSize = 6 * MBYTE;
                    //fileExplorerSP.Skin = SKIN;
                    AddOwnerAndModificationColumns();
                }
                else
                {
                    panelUserInformation.Visible = true;
                    panelHintMessage.Visible = true;
                    panelFileExplorer.Visible = false;
                    tbHintMessage.Text = "Sorry...\n" + "You don't have any document library under site: " + objSelectedSPUrl;
                    if (TempCredential[this.UserInfo.Username])
                    {
                        tbModuleUserName.Text = DecryptInformation(TempSPUserName[this.UserInfo.Username]);
                        tbModulePassword.Attributes["Value"] = DecryptInformation(TempSPPassword[this.UserInfo.Username]);
                    }
                    else
                    {
                        tbModuleUserName.Text = DecryptInformation(this.UserInfo.Profile.GetPropertyValue("SPUserName"));
                        tbModulePassword.Attributes["Value"] = DecryptInformation(this.UserInfo.Profile.GetPropertyValue("SPPassword"));
                    }
                }
            }
            catch
            {
                throw;
            }
        }

        // View Paths
        private List<string> PreparePaths(string sharepointUrl, List<string> documentLibraries)
        {
            List<string> viewPaths = new List<string>();
            if (!sharepointUrl.EndsWith("/"))
                sharepointUrl += "/";
            if (documentLibraries != null)
            {
                foreach (var documentLibrary in documentLibraries)
                    viewPaths.Add(sharepointUrl + documentLibrary);
            }
            return viewPaths;
        }

        // Add a custom column
        private void AddGridColumn(string name, string uniqueName, bool sortable)
        {
            // remove first if grid has a column with that name
            RemoveGridColumn(uniqueName);
            // add a new column with the specified name
            GridTemplateColumn gridTemplateColumn = new GridTemplateColumn();
            gridTemplateColumn.HeaderText = name;
            if (sortable)
                gridTemplateColumn.SortExpression = uniqueName;
            gridTemplateColumn.UniqueName = uniqueName;
            gridTemplateColumn.DataField = uniqueName;
            fileExplorerSP.Grid.Columns.Add(gridTemplateColumn);
        }

        // Remove a custom column
        private void RemoveGridColumn(string uniqueName)
        {
            if (!object.Equals(fileExplorerSP.Grid.Columns.FindByUniqueNameSafe(uniqueName), null))
            {
                fileExplorerSP.Grid.Columns.Remove(fileExplorerSP.Grid.Columns.FindByUniqueName(uniqueName));
            }
        }

        // Add Owner and ModificationTime columns
        private void AddOwnerAndModificationColumns()
        {
            AddGridColumn("Modification Date", "ModificationDate", false);
            AddGridColumn("Owner Name", "OwnerName", false);
        }

        protected void btnShowDocumentLibraries_OnClick(object sender, EventArgs e)
        {
            Dictionary<string, bool> tempCredential = new Dictionary<string, bool>();
            Dictionary<string, string> tempSPUserName = new Dictionary<string, string>();
            Dictionary<string, string> tempSPPassword = new Dictionary<string, string>();
            tbModulePassword.Attributes.Add("Value", tbModulePassword.Text.TrimEnd());
            if (chkBoxRememberInfo.Checked)
            {
                tempCredential.Clear();
                tempCredential.Add(this.UserInfo.Username, false);
                TempCredential = tempCredential;
                this.UserInfo.Profile.SetProfileProperty("SPUserName", EncryptInformation(tbModuleUserName.Text.TrimEnd()));
                this.UserInfo.Profile.SetProfileProperty("SPPassword", EncryptInformation(tbModulePassword.Text.TrimEnd()));
                UserController.UpdateUser(this.PortalId, this.UserInfo);
                TempSPDomian = (string)Settings["SP_DOMAIN"];
            }
            else
            {
                tempCredential.Clear();
                tempSPUserName.Clear();
                tempSPPassword.Clear();
                tempCredential.Add(this.UserInfo.Username, true);
                // Encrypted information
                tempSPUserName.Add(this.UserInfo.Username, EncryptInformation(tbModuleUserName.Text.TrimEnd()));
                tempSPPassword.Add(this.UserInfo.Username, EncryptInformation(tbModulePassword.Text.TrimEnd()));
                TempCredential = tempCredential;
                TempSPUserName = tempSPUserName;
                TempSPPassword = tempSPPassword;
                // SPContentProvider needs domain again
                TempSPDomian = (string)Settings["SP_DOMAIN"];
            }
            Response.Redirect(Request.Url.PathAndQuery);
        }

        private string EncryptInformation(string information)
        {
            return portalSecurity.Encrypt(encryptionKey, information);
        }

        private string DecryptInformation(string information)
        {
            return portalSecurity.Decrypt(encryptionKey, information);
        }

        protected void btnLogout_OnClick(object sender, EventArgs e)
        {
            // check whether information is sessioned or saved
            if (!(string.IsNullOrEmpty(this.UserInfo.Profile.GetPropertyValue("SPUserName")) || string.IsNullOrEmpty(this.UserInfo.Profile.GetPropertyValue("SPPassword"))))
            {
                this.UserInfo.Profile.SetProfileProperty("SPUserName", string.Empty);
                this.UserInfo.Profile.SetProfileProperty("SPPassword", string.Empty);
                UserController.UpdateUser(this.PortalId, this.UserInfo);
            }
            else
            {
                TempSPUserName = null;
                TempSPPassword = null;
                TempCredential = null;
            }
            Response.Redirect(Request.Url.PathAndQuery);
        }

        protected void comboboxSkins_OnSelectedIndexChanged(object sender, RadComboBoxSelectedIndexChangedEventArgs e)
        {
            if (comboboxSkins.SelectedItem != null)
            {
                if (comboboxSkins.SelectedItem.Text.ToLower() == "gray")
                    fileExplorerSP.Skin = "Telerik";
                if (comboboxSkins.SelectedItem.Text.ToLower() == "blue")
                    fileExplorerSP.Skin = "Office2007";
                if (comboboxSkins.SelectedItem.Text.ToLower() == "darkblue")
                    fileExplorerSP.Skin = "Web20";
            }
        }
    }
}